home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / HENSA / MATHS / PLPLOT / PLPLOT.ZIP / sys / dos / djgpp / src / gnusvga.c next >
Encoding:
C/C++ Source or Header  |  1994-08-11  |  14.6 KB  |  562 lines

  1. /* $Id: gnusvga.c,v 1.2 1994/08/10 20:23:47 mjl Exp $
  2.  * $Log: gnusvga.c,v $
  3.  * Revision 1.2  1994/08/10  20:23:47  mjl
  4.  * Latest changes for DJGPP port by Paul Kirschner.
  5.  *
  6.  * Revision 1.1  1994/08/10  01:08:29  mjl
  7.  * New directory structure, config files, and other modifications for PLplot
  8.  * 4.99h/djgpp DOS port, submitted by Paul Kirschner.  New driver supports
  9.  * color fill.
  10.  *
  11.  * Revision 1.1  1994/05/25  09:19:22  mjl
  12.  * The new locations for DJGPP (DOS 386) files.
  13.  *
  14.  * Revision 1.14  1994/04/08  11:35:57  mjl
  15.  * Put nopause support back into the drivers where it is better off.
  16.  * I don't know WHAT I was thinking.
  17.  *
  18.  * Revision 1.13  1994/03/23  06:34:23  mjl
  19.  * All drivers: cleaned up by eliminating extraneous includes (stdio.h and
  20.  * stdlib.h now included automatically by plplotP.h), extraneous clears
  21.  * of pls->fileset, pls->page, and pls->OutFile = NULL (now handled in
  22.  * driver interface or driver initialization as appropriate).  Special
  23.  * handling for malloc includes eliminated (no longer needed) and malloc
  24.  * prototypes fixed as necessary.
  25.  *
  26.  * Revision 1.12  1993/12/08  06:12:22  mjl
  27.  * Miscellaneous bug fixes contributed by Paul Kirschner.
  28.  *
  29.  * Revision 1.11  1993/07/31  07:56:30  mjl
  30.  * Several driver functions consolidated, for all drivers.  The width and color
  31.  * commands are now part of a more general "state" command.  The text and
  32.  * graph commands used for switching between modes is now handled by the
  33.  * escape function (very few drivers require it).  The device-specific PLDev
  34.  * structure is now malloc'ed for each driver that requires it, and freed when
  35.  * the stream is terminated.
  36.  *
  37.  * Revision 1.10  1993/07/16  22:11:15  mjl
  38.  * Eliminated low-level coordinate scaling; now done by driver interface.
  39.  *
  40.  * Revision 1.9  1993/07/01  21:59:33  mjl
  41.  * Changed all plplot source files to include plplotP.h (private) rather than
  42.  * plplot.h.  Rationalized namespace -- all externally-visible plplot functions
  43.  * now start with "pl"; device driver functions start with "plD_".
  44. */
  45.  
  46. /*
  47.     gnusvga.c
  48.     Geoffrey Furnish
  49.     20 March 1992
  50.     
  51.     This file constitutes the driver for an SVGA display under DOS
  52.     using the GNU CC compiler and grpahics library by DJ Delorie.
  53.  
  54.     There are some things to note:
  55.     1)  DJ Delorie's DOS port of GNU CC 386 uses a VCPI DOS extender.
  56.         This means, among other things, that it won't run under
  57.         any flavor of OS/2.  A DPMI port was rumored to be
  58.         underway, so it is possible that by the time you read
  59.         this, this restriction will have been lifted.
  60.     2)  The currently available video drivers only support Super VGA
  61.         type display cards, and only in resolutions with 256
  62.         colors.  Thus, if you only have regular VGA, you're gonna
  63.         get 320 x 200 resolution.  On the other hand, if you do
  64.         have a card with say, 800 x 600 x 256 colors, then you're
  65.         gonna get a picture much better than what could be delivered
  66.         by the standard DOS version of PLPLOT using Micrsoft
  67.         graphics.
  68.     3)  This driver supports the PLPLOT RGB escape function.  So, you
  69.         can draw lines of any color you like, which is again
  70.         superior to the standard DOS version based on MS graphics.
  71. */
  72. #include "plDevs.h"
  73.  
  74. #ifdef PLD_gnusvga        /* Only compile for DOS 386 with GNU CC
  75.                    compiler */
  76. #include "plplotP.h"
  77. #include "drivers.h"
  78. #include "plevent.h"
  79. #include <graphics.h>
  80.  
  81. /* Prototypes:    Since GNU CC, we can rest in the safety of ANSI prototyping. */
  82.  
  83. static void    plpause        (PLStream *);
  84. static void    init_palette    (void);
  85. static void    svga_text    (PLStream *);
  86. static void    svga_graph    (PLStream *);
  87.  
  88. static void    fill_polygon    (PLStream *pls);
  89. static void    setcmap        (PLStream *pls);
  90. static void    WaitForPage    (PLStream *pls);
  91. static void    EventHandler    (PLStream *pls, int input_char);
  92.  
  93. static PLINT vgax = 639;
  94. static PLINT vgay = 479;
  95.  
  96. /* A flag to tell us whether we are in text or graphics mode */
  97.  
  98. #define TEXT_MODE 0
  99. #define GRAPHICS_MODE 1
  100.  
  101. /* gmf; should probably query this on start up... Maybe later. */
  102.  
  103. static int mode = TEXT_MODE;
  104. static int col = 1;
  105. static int totcol = 16;
  106. static exit_eventloop = 0;
  107.  
  108. #define CLEAN 0
  109. #define DIRTY 1
  110.  
  111. static page_state;
  112.  
  113. typedef struct {
  114.     int r;
  115.     int g;
  116.     int b;
  117. } RGB;
  118.  
  119. static RGB colors[] = {
  120.     {0, 0, 0},            /* coral */
  121.     {255, 0, 0},        /* red */
  122.     {255, 255, 0},        /* yellow */
  123.     {0, 255, 0},        /* green */
  124.     {127, 255, 212},        /* acquamarine */
  125.     {255, 192, 203},        /* pink */
  126.     {245, 222, 179},        /* wheat */
  127.     {190, 190, 190},        /* grey */
  128.     {165, 42, 42},        /* brown */
  129.     {0, 0, 255},        /* blue */
  130.     {138, 43, 226},        /* Blue Violet */
  131.     {0, 255, 255},        /* cyan */
  132.     {64, 224, 208},        /* turquoise */
  133.     {255, 0, 255},        /* magenta */
  134.     {250, 128, 114},        /* salmon */
  135.     {255, 255, 255},        /* white */
  136.     {0, 0, 0},            /* black */
  137. };
  138.  
  139.  
  140. /*----------------------------------------------------------------------*\
  141.  * plD_init_vga()
  142.  *
  143.  * Initialize device.
  144. \*----------------------------------------------------------------------*/
  145.  
  146. void
  147. plD_init_vga(PLStream *pls)
  148. {
  149.     pls->termin = 1;        /* is an interactive terminal */
  150.     pls->icol0 = 1;
  151.     pls->width = 1;
  152.     pls->bytecnt = 0;
  153.     pls->page = 0;
  154.     pls->graphx = TEXT_MODE;
  155.  
  156.     pls->dev_fill0 = 1;
  157.  
  158.     if (!pls->colorset)
  159.     pls->color = 1;
  160.  
  161. /* Set up device parameters */
  162.  
  163.     svga_graph(pls);        /* Can't get current device info unless in
  164.                    graphics mode. */
  165.  
  166.     vgax = GrSizeX() - 1;    /* should I use -1 or not??? */
  167.     vgay = GrSizeY() - 1;
  168.  
  169.     plP_setpxl(2.5, 2.5);    /* My best guess.  Seems to work okay. */
  170.  
  171.     plP_setphy(0, vgax, 0, vgay);
  172. }
  173.  
  174. /*----------------------------------------------------------------------*\
  175.  * plD_line_vga()
  176.  *
  177.  * Draw a line in the current color from (x1,y1) to (x2,y2).
  178. \*----------------------------------------------------------------------*/
  179.  
  180. void
  181. plD_line_vga(PLStream *pls, short x1a, short y1a, short x2a, short y2a)
  182. {
  183.     int x1 = x1a, y1 = y1a, x2 = x2a, y2 = y2a;
  184.  
  185.     y1 = vgay - y1;
  186.     y2 = vgay - y2;
  187.  
  188.     GrLine(x1, y1, x2, y2, col);
  189.  
  190.     page_state = DIRTY;
  191. }
  192.  
  193. /*----------------------------------------------------------------------*\
  194.  * plD_polyline_vga()
  195.  *
  196.  * Draw a polyline in the current color.
  197. \*----------------------------------------------------------------------*/
  198.  
  199. void
  200. plD_polyline_vga(PLStream *pls, short *xa, short *ya, PLINT npts)
  201. {
  202.     PLINT i;
  203.  
  204.     for (i = 0; i < npts - 1; i++)
  205.     plD_line_vga(pls, xa[i], ya[i], xa[i + 1], ya[i + 1]);
  206. }
  207.  
  208. /*----------------------------------------------------------------------*\
  209.  * plD_eop_vga()
  210.  *
  211.  * End of page.
  212. \*----------------------------------------------------------------------*/
  213.  
  214. void
  215. plD_eop_vga(PLStream *pls)
  216. {
  217.     if (page_state == DIRTY) {
  218.     if ( ! pls->nopause) 
  219.         WaitForPage(pls);
  220.     }
  221.  
  222. /*     init_palette(); */
  223.  
  224.     page_state = CLEAN;
  225. }
  226.  
  227. /*----------------------------------------------------------------------*\
  228.  * plD_bop_vga()
  229.  *
  230.  * Set up for the next page.
  231.  * Advance to next family file if necessary (file output).
  232. \*----------------------------------------------------------------------*/
  233.  
  234. void
  235. plD_bop_vga(PLStream *pls)
  236. {
  237.     pls->page++;
  238.     plD_eop_vga(pls);
  239.     GrClearScreen(0);
  240. }
  241.  
  242. /*----------------------------------------------------------------------*\
  243.  * plD_tidy_vga()
  244.  *
  245.  * Close graphics file or otherwise clean up.
  246. \*----------------------------------------------------------------------*/
  247.  
  248. void
  249. plD_tidy_vga(PLStream *pls)
  250. {
  251.     svga_text(pls);
  252. }
  253.  
  254. /*----------------------------------------------------------------------*\
  255.  * plD_state_vga()
  256.  *
  257.  * Handle change in PLStream state (color, pen width, fill attribute, etc).
  258. \*----------------------------------------------------------------------*/
  259.  
  260. void 
  261. plD_state_vga(PLStream *pls, PLINT op)
  262. {
  263.     switch (op) {
  264.  
  265.     case PLSTATE_WIDTH:
  266.     break;
  267.  
  268.     case PLSTATE_COLOR0:
  269.     col = pls->icol0;
  270.     if (col == PL_RGB_COLOR) {
  271.         int r = pls->curcolor.r;
  272.         int g = pls->curcolor.g;
  273.         int b = pls->curcolor.b;
  274.         if (totcol < GrNumColors()) {
  275.         GrSetColor(++totcol, r, g, b);
  276.         col = totcol;
  277.         }
  278.     }
  279.     break;
  280.  
  281.     case PLSTATE_COLOR1:
  282.         { int icol1, ncol1, r, g, b;
  283.         if ((ncol1 = MIN(GrNumColors() - pls->ncol0, pls->ncol1)) < 1)
  284.             break;
  285.  
  286.         icol1 = pls->ncol0 + (pls->icol1 * (ncol1-1)) / (pls->ncol1-1);
  287.  
  288.         r = pls->curcolor.r;
  289.         g = pls->curcolor.g;
  290.         b = pls->curcolor.b;
  291.         GrSetColor(icol1, r, g, b);
  292.         col = icol1;
  293.     }
  294.     break;
  295.  
  296.     case PLSTATE_CMAP0:
  297.     case PLSTATE_CMAP1:
  298.     if (pls->color)
  299.         setcmap(pls);
  300.     break;
  301.     }
  302. }
  303.  
  304. /*----------------------------------------------------------------------*\
  305.  * plD_esc_vga()
  306.  *
  307.  * Escape function.
  308. \*----------------------------------------------------------------------*/
  309.  
  310. void
  311. plD_esc_vga(PLStream *pls, PLINT op, void *ptr)
  312. {
  313.     switch (op) {
  314.       case PLESC_TEXT:
  315.     svga_text(pls);
  316.     break;
  317.  
  318.       case PLESC_GRAPH:
  319.     svga_graph(pls);
  320.     break;
  321.  
  322.       case PLESC_FILL:
  323.     fill_polygon(pls);
  324.     break;
  325.     }
  326. }
  327.  
  328. /*----------------------------------------------------------------------*\
  329.  * fill_polygon()
  330.  *
  331.  * Fill polygon described in points pls->dev_x[] and pls->dev_y[].
  332. \*----------------------------------------------------------------------*/
  333.  
  334. static void
  335. fill_polygon(PLStream *pls)
  336. {
  337.     int i;
  338.     int points[PL_MAXPOLY][2];
  339.  
  340.     if (pls->dev_npts < 1)
  341.     return;
  342.  
  343. /* Select the fill pattern */
  344.  
  345. /* Specify boundary */
  346.  
  347.     for (i = 0; i < pls->dev_npts; i++) {
  348.     points[i][0] = pls->dev_x[i];
  349.         points[i][1] = vgay - pls->dev_y[i];
  350.     }
  351.     GrFilledPolygon(pls->dev_npts, points, col);
  352.  
  353. }
  354.  
  355. /*----------------------------------------------------------------------*\
  356.  * svga_text()
  357.  *
  358.  * Switch to text mode.
  359. \*----------------------------------------------------------------------*/
  360.  
  361. static void
  362. svga_text(PLStream *pls)
  363. {
  364.     if (pls->graphx == GRAPHICS_MODE) {
  365.     if (page_state == DIRTY)
  366.         plpause(pls);
  367.     GrSetMode(GR_default_text);
  368.     GrResetColors();
  369.     pls->graphx = TEXT_MODE;
  370.     page_state = CLEAN;
  371.     }
  372. }
  373.  
  374. /*----------------------------------------------------------------------*\
  375.  * svga_graph()
  376.  *
  377.  * Switch to graphics mode.
  378.  *
  379.  * NOTE: Moving to a new page causes the RGB map to be reset so that
  380.  * there will continue to be room.  This could conceivably cause a
  381.  * problem if an RGB escape was used to start drawing in a new color, and
  382.  * then it was expected that this would persist accross a page break.  If
  383.  * this happens, it will be necessary to rethink the logic of how this is
  384.  * handled.  Could wrap the index, for example.  This would require
  385.  * saving the RGB info used so far, which is not currently done.
  386. \*----------------------------------------------------------------------*/
  387.  
  388. static void
  389. svga_graph(PLStream *pls)
  390. {
  391.     if (pls->graphx == TEXT_MODE) {
  392.                 /* Destroys the palette */
  393.     GrSetMode(GR_default_graphics);
  394. /*    GrSetMode(GR_320_200_graphics); */
  395.     init_palette();        /* Fix the palette */
  396.     totcol = 16;        /* Reset RGB map so we don't run out of
  397.                    indicies */
  398.     pls->graphx = GRAPHICS_MODE;
  399.     page_state = CLEAN;
  400.     }
  401. }
  402.  
  403. /*----------------------------------------------------------------------*\
  404.  * plpause()
  405.  *
  406.  * Wait for a keystroke.
  407. \*----------------------------------------------------------------------*/
  408.  
  409. static void
  410. plpause(PLStream *pls)
  411. {
  412.     if (pls->nopause) 
  413.     return;
  414.  
  415.     GrTextXY(0, 0, "Pause->", 15, 0);
  416.     getkey();
  417. }
  418.  
  419. /*----------------------------------------------------------------------*\
  420.  * setcmap()
  421.  *
  422.  * Sets up color palette.
  423. \*----------------------------------------------------------------------*/
  424.  
  425. static void
  426. setcmap(PLStream *pls)
  427. {
  428.     int i, ncol1;
  429.     PLColor cmap1col;
  430.  
  431. /* Initialize cmap 0 colors */
  432.  
  433.     for (i = 0; i < pls->ncol0; i++) 
  434.     GrSetColor(i, pls->cmap0[i].r, pls->cmap0[i].g, pls->cmap0[i].b);
  435.  
  436. /* Initialize any remaining slots for cmap1 */
  437.  
  438.     ncol1 = GrNumFreeColors();
  439.     for (i = 0; i < ncol1; i++) {
  440.     plcol_interp(pls, &cmap1col, i, ncol1);
  441.     GrSetColor(i + pls->ncol0, cmap1col.r, cmap1col.g, cmap1col.b);
  442.     }
  443. }
  444.  
  445. /*----------------------------------------------------------------------*\
  446.  * init_palette()
  447.  *
  448.  * Set up the nice RGB default color map.
  449. \*----------------------------------------------------------------------*/
  450.  
  451. static void 
  452. init_palette(void)
  453. {
  454.     int n;
  455.  
  456.     for (n = 0; n < sizeof(colors) / sizeof(RGB); n++)
  457.     GrSetColor(n, colors[n].r, colors[n].g, colors[n].b);
  458. }
  459.  
  460. /*----------------------------------------------------------------------*\
  461.  * WaitForPage()
  462.  *
  463.  * This routine waits for the user to advance the plot, while handling
  464.  * all other events.
  465. \*----------------------------------------------------------------------*/
  466.  
  467. static void
  468. WaitForPage(PLStream *pls)
  469. {
  470.     int input_char;
  471.  
  472. /*    putchar(BEL); */
  473. /*    fflush(stdout); */
  474.  
  475.     while ( ! exit_eventloop) {
  476.     input_char = getkey();
  477.     EventHandler(pls, input_char);
  478.     }
  479.     exit_eventloop = FALSE;
  480. }
  481.  
  482. /*----------------------------------------------------------------------*\
  483.  * EventHandler()
  484.  *
  485.  * Event handler routine for xterm.  
  486.  * Just reacts to keyboard input.
  487. \*----------------------------------------------------------------------*/
  488.  
  489. static void
  490. EventHandler(PLStream *pls, int input_char)
  491. {
  492.     PLKey key;
  493.  
  494.     key.code = 0;
  495.     key.string[0] = '\0';
  496.  
  497. /* Translate keystroke into a PLKey */
  498.  
  499.     if ( ! isprint(input_char)) {
  500.     switch (input_char) {
  501.     case 0x0A:
  502.         key.code = PLK_Linefeed;
  503.         break;
  504.  
  505.     case 0x0D:
  506.         key.code = PLK_Return;
  507.         break;
  508.  
  509.     case 0x08:
  510.         key.code = PLK_BackSpace;
  511.         break;
  512.  
  513.     case 0x7F:
  514.         key.code = PLK_Delete;
  515.         break;
  516.     }
  517.     }
  518.     else {
  519.     key.string[0] = input_char;
  520.     key.string[1] = '\0';
  521.     }
  522.  
  523. #ifdef DEBUG
  524.     pltext();
  525.     fprintf(stderr, "Input char %x, Keycode %x, string: %s\n",
  526.         input_char, key.code, key.string);
  527.     plgra();
  528. #endif
  529.  
  530. /* Call user event handler */
  531. /* Since this is called first, the user can disable all plplot internal
  532.    event handling by setting key.code to 0 and key.string to '\0' */
  533.  
  534.     if (pls->KeyEH != NULL)
  535.     (*pls->KeyEH) (&key, pls->KeyEH_data, &exit_eventloop);
  536.  
  537. /* Handle internal events */
  538.  
  539. /* Advance to next page (i.e. terminate event loop) on a <eol> */
  540.  
  541.     if (key.code == PLK_Linefeed)
  542.     exit_eventloop = TRUE;
  543.     if (key.code == PLK_Return)
  544.     exit_eventloop = TRUE;
  545.  
  546. /* Terminate on a 'Q' (not 'q', since it's too easy to hit by mistake) */
  547.  
  548.     if (key.string[0] == 'Q') {
  549.     pls->nopause = TRUE;
  550.     plexit("");
  551.     }
  552. }
  553.  
  554. #else
  555. int 
  556. pldummy_gnusvga()
  557. {
  558.     return 0;
  559. }
  560.  
  561. #endif                /* GNUSVGA */
  562.